package com.apps.shelper;

import com.apps.sannotation.service.enums.CacheModel;
import com.apps.sexctption.NullException;
import com.apps.sutils.StringUtils;
import com.baomidou.mybatisplus.annotation.TableId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * redis操作
 */
@Component
public class RedisCacheHelper
{
    /**
     * redis操作类
     */
    private static RedisTemplate<String,Object> redisTemplate;
    /**
     * 索引表的前缀
     */
    private static String indexes_key_prefix="innex_";

    @Autowired
    public void setRedisTemplate(RedisTemplate<String,Object> sRedisTemplate)
    {
        redisTemplate = sRedisTemplate;
    }
    /**
     * 获取对象的自增字段的名称
     * @return
     */
    public static String getTableIdName(Class<?> cla)
    {
        return AnnotationHelper.getAnnotationFieldName(TableId.class,cla);
    }

    /**
     * 往缓存插入数据
     * @param obj
     * @param cla
     * @param is_cover 如果已存在是否覆盖
     */
    public static void add(Object obj,Class<?> cla,boolean is_cover)
    {
        if(null == obj)
            return;
        //如果没有配置使用缓存则直接返回
        CacheModel cacheModel=ClassHelper.getClassCacheModel(cla);
        if(null == cacheModel)
            return;
        //获取自增id的名称
        String tableIdName=getTableIdName(obj.getClass());
        if(StringUtils.isEmpty(tableIdName))
            throw new NullException("自增id字段不存在");
        //获取自增id的值
        Object tableIdVal=ClassHelper.getFiledValue(obj,tableIdName);
        if(null ==tableIdVal)
            throw new NullException("自增id字段不能为空");
        //如果缓存有这条数据则返回
        if(!is_cover && null!=redisTemplate.opsForHash().get(cla.getSimpleName(),tableIdVal.toString()))
            return;
        //压入缓存
        redisTemplate.opsForHash().put(cla.getSimpleName(),tableIdVal.toString(),obj);
        //添加索引
        GenerateIndexes(cla,obj,tableIdVal.toString());
    }

    /**
     * 批量插入缓存
     * @param obj
     * @param cla
     */
    public static void add(List<Object> obj,Class<?> cla,boolean is_cover)
    {
        if(null == obj)
            return;
        //如果没有配置使用缓存则直接返回
        CacheModel cacheModel=ClassHelper.getClassCacheModel(cla);
        if(null == cacheModel)
            return;
        for(int i=0;i<obj.size();i++) {
            add(obj.get(i), cla, is_cover);
        }

    }

    /**
     * 从缓存中删除数据
     * @param obj
     * @param cla
     */
    public static void delete(List<Object> obj,Class<?> cla)
    {
        if(null == obj)
            return;
        //如果没有配置使用缓存则直接返回
        CacheModel cacheModel=ClassHelper.getClassCacheModel(cla);
        if(null == cacheModel)
            return;
        //获取索引的表key
        String indexes_key=indexes_key_prefix+cla.getSimpleName();
        for(int i=0;i<obj.size();i++)
        {
            //获取自增id的名称
            String tableIdName = getTableIdName(obj.get(i).getClass());
            if (StringUtils.isEmpty(tableIdName))
                throw new NullException("自增id字段不存在");
            //获取自增id的值
            Object tableIdVal = ClassHelper.getFiledValue(obj.get(i), tableIdName);
            if (null == tableIdVal)
                throw new NullException("自增id字段不能为空");
            //清空索引
            CleanIndexes(indexes_key, tableIdVal.toString());
            //删除对象
            redisTemplate.opsForHash().delete(cla.getSimpleName(),tableIdVal.toString());
        }
    }
    /**
     * 查询一条数据
     * @param filed_name
     * @param filed_val
     * @return
     */
    public static Object getOne(String filed_name,String filed_val,Class<?> cla)
    {
        //如果没有配置使用缓存则直接返回
        CacheModel cacheModel=ClassHelper.getClassCacheModel(cla);
        if(null == cacheModel)
            return null;
        String indexes_key=indexes_key_prefix+cla.getSimpleName();
        String indexes=filed_name+"_"+filed_val;
        Set hashSet = (Set) redisTemplate.opsForHash().get(indexes_key,indexes);
        if(null == hashSet || hashSet.size()<=0)
            return null;
        return redisTemplate.opsForHash().get(cla.getSimpleName(),hashSet.toArray()[0]);
    }

    /**
     * 查询一条数据
     * @param obj
     * @param cla
     * @return
     */
    public static Object getOne(Object obj,Class<?> cla)
    {
        if(null == obj)
            return null;
        //获取自增id的名称
        String tableIdName = getTableIdName(obj.getClass());
        if (StringUtils.isEmpty(tableIdName))
            throw new NullException("自增id字段不存在");
        //获取自增id的值
        Object tableIdVal = ClassHelper.getFiledValue(obj, tableIdName);
        if (null == tableIdVal)
            throw new NullException("自增id字段不能为空");
        //返回结果
        return getOne(tableIdName,tableIdVal.toString(),cla);
    }

    /**
     * 按条件批量查询
     * @param filed_name
     * @param filed_val
     * @param cla
     * @return
     */
    public static List<Object> query(String filed_name,String filed_val,Class<?> cla)
    {
        //如果没有配置使用缓存则直接返回
        CacheModel cacheModel=ClassHelper.getClassCacheModel(cla);
        if(null == cacheModel)
            return null;
        //如果不是全在缓存操作的模式则返回null,这种模式必须走数据库查询
        if(cacheModel != CacheModel.ALL)
            return null;
        String indexes_key=indexes_key_prefix+cla.getSimpleName();
        String indexes=filed_name+"_"+filed_val;
        Set hashSet = (Set) redisTemplate.opsForHash().get(indexes_key,indexes);
        if(null == hashSet || hashSet.size()<=0)
            return null;
        //结果集
        List<Object> result=new ArrayList<>();
        for (Iterator iter = hashSet.iterator(); iter.hasNext();)
        {
            result.add(iter.hasNext());
        }
        return result;
    }
    /**
     * 查出一张表所有的数据
     * @param cla
     * @return
     */
    public static List<Object> query(Class<?> cla)
    {
        //如果没有配置使用缓存则直接返回
        CacheModel cacheModel=ClassHelper.getClassCacheModel(cla);
        if(null == cacheModel)
            return null;
        //如果不是全在缓存操作的模式则返回null,这种模式必须走数据库查询
        if(cacheModel != CacheModel.ALL)
            return null;
        List<Object> result=new ArrayList<>(redisTemplate.opsForHash().entries(cla.getSimpleName()).values());
        return result;
    }
    /**
     * 给存储对象生成索引
     * @param cla
     * @param obj
     * @param target_key
     */
    public static void GenerateIndexes(Class<?> cla,Object obj,String target_key)
    {
        String indexes_key=indexes_key_prefix+cla.getSimpleName();
        List<String> indexes=ClassHelper.getModelIndexes(obj);
        //如果不是第一次创建则先清空该对象的索引
        if(null!=getOne(obj,cla))
           CleanIndexes(indexes_key,target_key);
        //添加索引
        for(String index:indexes)
        {
            Set hashSet = (Set) redisTemplate.opsForHash().get(indexes_key_prefix+cla.getSimpleName(),index);
            if(null==hashSet)
                hashSet = new HashSet();
            hashSet.add(target_key);
            redisTemplate.opsForHash().put(indexes_key,index,hashSet);
        }

    }

    /**
     * 清空某个对象的索引
     * @param indexes_key
     * @param target_key
     */
    public static void CleanIndexes(String indexes_key,String target_key)
    {
        Set<Object> keys=redisTemplate.opsForHash().entries(indexes_key).keySet();
        for (Iterator iter = keys.iterator(); iter.hasNext();)
        {
            String index= (String) iter.next();
            Set hashSet = (Set) redisTemplate.opsForHash().get(indexes_key,index);
            if(null==hashSet)
                continue;
            if(hashSet.contains(target_key)) {
                hashSet.remove(target_key);
                //塞回去
                redisTemplate.opsForHash().put(indexes_key, index, hashSet);
            }
        }
    }

}
